//
// Created by DengLibin on 2018/12/12 0012.
//

/**
 *static 关键字
 * 作用：
 * 1、隐藏：当同时编译多个文件时，所有未加static前缀的全局变量和函数都具有全局可见性（一个文件定义的变量，其他文件也可访问）
 * 2、保持变量内容的持久：
 *      存储在静态数据区的变量会在程序刚开始运行时就完成初始化，也是唯一的一次初始化。共有两种变量存储在静态存储区：全局变量和static变量，
 *      只不过和全局变量比起来，static可以控制变量的可见范围，说到底static还是用来隐藏的。虽然这种用法不常见
        PS：如果作为static局部变量在函数内定义，它的生存期为整个源程序，但是其作用域仍与自动变量相同，只能在定义该变量的函数内使用该变量。退出该函数后， 尽管该变量还继续存在，但不能使用它。
       例：
       int fun(){
             static int count = 10; //在第一次进入这个函数的时候，变量a被初始化为10！并接着自减1，以后每次进入该函数，a 就不会被再次初始化了，仅进行自减1的操作；在static发明前，要达到同样的功能，则只能使用全局变量：
             return count--;
        }
  3、默认初始化为0（static变量）

  4、C++中的类成员声明static
        在类中声明static变量或者函数时，初始化时使用作用域运算符来标明它所属类，因此，静态数据成员是类的成员，而不是对象的成员，这样就出现以下作用：

(1)类的静态成员函数是属于整个类而非类的对象，所以它没有this指针，这就导致 了它仅能访问类的静态数据和静态成员函数。

(2)不能将静态成员函数定义为虚函数。

(3)由于静态成员声明于类中，操作于其外，所以对其取地址操作，就多少有些特殊 ，变量地址是指向其数据类型的指针 ，函数地址类型是一个“nonmember函数指针”。

(4)由于静态成员函数没有this指针，所以就差不多等同于nonmember函数，结果就 产生了一个意想不到的好处：成为一个callback函数，使得我们得以将C++和C-based X W indow系统结合，同时也成功的应用于线程函数身上。 （这条没遇见过）

(5)static并没有增加程序的时空开销，相反她还缩短了子类对父类静态成员的访问 时间，节省了子类的内存空间。

(6)静态数据成员在<定义或说明>时前面加关键字static。

(7)静态数据成员是静态存储的，所以必须对它进行初始化。 （程序员手动初始化，否则编译时一般不会报错，但是在Link时会报错误）

(8)静态成员初始化与一般数据成员初始化不同:

初始化在类体外进行，而前面不加static，以免与一般静态变量或对象相混淆；
初始化时不加该成员的访问权限控制符private，public等；
初始化时使用作用域运算符来标明它所属类；
           所以我们得出静态数据成员初始化的格式：
<数据类型><类名>::<静态数据成员名>=<值>

(9)为了防止父类的影响，可以在子类定义一个与父类相同的静态变量，以屏蔽父类的影响。这里有一点需要注意：我们说静态成员为父类和子类共享，但我们有重复定义了静态成员，
 这会不会引起错误呢？不会，我们的编译器采用了一种绝妙的手法：name-mangling 用以生成唯一的标志。

 ps：静态成员为啥在类的外部定义再初始化：
1. 在类中，只是声明了静态变量，并没有定义。

2. 声明只是表明了变量的数据类型和属性，并不分配内存；定义则是需要分配内存的。    注意：如果在类里面这么写int a; 那么是既声明了变量，也定义了变量，两者合在一起了。

3. 静态成员是“类级别”的，也就是它和类的地位等同，而普通成员是“对象（实例）级别”的。    类级别的成员，先于该类任何对象的存在而存在，它被该类所有的对象共享。

4. 现在，咱们假定要实例化该类的一个对象，那么会发生什么事情呢？

 静态成员肯定要出现在这个对象里面的，对吧？这时候才去定义那个静态成员吗？这显然是不合适的。

 因为，比如有另外一个线程也要创建该类的对象，那么也要按照这个方式去定义那个静态成员。
 */
#include <iostream>
using namespace std;
static int a; //静态变量 默认 0

class StaticPerson
{
private:
    static int age; //在类中，只是声明了静态变量，并没有定义

public:
    static void show()
    {
        cout << "age = "<< age <<endl;
    }
};
int StaticPerson::age = 10; //类外部定义并初始化静态成员变量
int main11()
{
    StaticPerson::show();
    cout << "a = " << a << endl;
    return 0;
}